/*global pi */
pi.mod.define('pi.scene.query', function (pi) {
	"use strict";

	var module = {},
		queryList = pi.vector.create(),
		collisionList = pi.vector.create(),
		distanceBuff = pi.cbuffer.create(),
		vcalls = [
			["s3d_query_all", pi.vcall.TYPE_INT, [pi.vcall.TYPE_INT, pi.vcall.TYPE_INT, pi.vcall.TYPE_INT]],
			["s3d_query_frustum", pi.vcall.TYPE_INT, [pi.vcall.TYPE_INT, pi.vcall.TYPE_INT, pi.vcall.TYPE_INT, pi.vcall.TYPE_INT]],
			["s3d_collide_pair", pi.vcall.TYPE_INT, [pi.vcall.TYPE_INT, pi.vcall.TYPE_INT, pi.vcall.TYPE_INT, pi.vcall.TYPE_INT]],
			["s3d_query_sphere", pi.vcall.TYPE_INT, [pi.vcall.TYPE_INT, pi.vcall.TYPE_INT, pi.vcall.TYPE_INT, pi.vcall.TYPE_FLOAT, pi.vcall.TYPE_FLOAT, pi.vcall.TYPE_FLOAT, pi.vcall.TYPE_FLOAT]],
			["s3d_collision_sphere2objs", pi.vcall.TYPE_VOID, [pi.vcall.TYPE_INT, pi.vcall.TYPE_INT, pi.vcall.TYPE_INT, pi.vcall.TYPE_FLOAT, pi.vcall.TYPE_FLOAT, pi.vcall.TYPE_FLOAT, pi.vcall.TYPE_FLOAT]],
			["s3d_query_cube", pi.vcall.TYPE_INT, [pi.vcall.TYPE_INT, pi.vcall.TYPE_INT, pi.vcall.TYPE_INT, pi.vcall.TYPE_FLOAT, pi.vcall.TYPE_FLOAT, pi.vcall.TYPE_FLOAT, pi.vcall.TYPE_FLOAT, pi.vcall.TYPE_FLOAT, pi.vcall.TYPE_FLOAT]],
			["s3d_collision_cube2objs", pi.vcall.TYPE_VOID, [pi.vcall.TYPE_INT, pi.vcall.TYPE_INT, pi.vcall.TYPE_INT, pi.vcall.TYPE_FLOAT, pi.vcall.TYPE_FLOAT, pi.vcall.TYPE_FLOAT, pi.vcall.TYPE_FLOAT, pi.vcall.TYPE_FLOAT, pi.vcall.TYPE_FLOAT]],
			["s3d_query_plane", pi.vcall.TYPE_INT, [pi.vcall.TYPE_INT, pi.vcall.TYPE_INT, pi.vcall.TYPE_INT, pi.vcall.TYPE_FLOAT, pi.vcall.TYPE_FLOAT, pi.vcall.TYPE_FLOAT, pi.vcall.TYPE_FLOAT]],
			["s3d_collision_plane2objs", pi.vcall.TYPE_VOID, [pi.vcall.TYPE_INT, pi.vcall.TYPE_INT, pi.vcall.TYPE_INT, pi.vcall.TYPE_FLOAT, pi.vcall.TYPE_FLOAT, pi.vcall.TYPE_FLOAT, pi.vcall.TYPE_FLOAT]],
			["s3d_query_sector", pi.vcall.TYPE_INT, [pi.vcall.TYPE_INT, pi.vcall.TYPE_INT, pi.vcall.TYPE_INT, pi.vcall.TYPE_FLOAT, pi.vcall.TYPE_FLOAT, pi.vcall.TYPE_POINTER]],
			["s3d_collision_sector2objs", pi.vcall.TYPE_VOID, [pi.vcall.TYPE_INT, pi.vcall.TYPE_INT, pi.vcall.TYPE_INT, pi.vcall.TYPE_FLOAT, pi.vcall.TYPE_FLOAT, pi.vcall.TYPE_POINTER, pi.vcall.TYPE_INT]],
			["s3d_query_cone", pi.vcall.TYPE_INT, [pi.vcall.TYPE_INT, pi.vcall.TYPE_INT, pi.vcall.TYPE_INT, pi.vcall.TYPE_FLOAT, pi.vcall.TYPE_FLOAT, pi.vcall.TYPE_POINTER]],
			["s3d_collision_cone2objs", pi.vcall.TYPE_VOID, [pi.vcall.TYPE_INT, pi.vcall.TYPE_INT, pi.vcall.TYPE_INT, pi.vcall.TYPE_FLOAT, pi.vcall.TYPE_FLOAT, pi.vcall.TYPE_POINTER, pi.vcall.TYPE_INT]],
			["s3d_query_cylinder", pi.vcall.TYPE_INT, [pi.vcall.TYPE_INT, pi.vcall.TYPE_INT, pi.vcall.TYPE_INT, pi.vcall.TYPE_FLOAT, pi.vcall.TYPE_FLOAT, pi.vcall.TYPE_POINTER]],
			["s3d_collision_cylinder2objs", pi.vcall.TYPE_VOID, [pi.vcall.TYPE_INT, pi.vcall.TYPE_INT, pi.vcall.TYPE_INT, pi.vcall.TYPE_FLOAT, pi.vcall.TYPE_FLOAT, pi.vcall.TYPE_POINTER, pi.vcall.TYPE_INT]],
			["s3d_query_line", pi.vcall.TYPE_VOID, [pi.vcall.TYPE_INT, pi.vcall.TYPE_INT, pi.vcall.TYPE_INT, pi.vcall.TYPE_FLOAT, pi.vcall.TYPE_FLOAT, pi.vcall.TYPE_FLOAT, pi.vcall.TYPE_FLOAT, pi.vcall.TYPE_FLOAT, pi.vcall.TYPE_FLOAT]],
			["s3d_collision_rayDist", pi.vcall.TYPE_VOID, [pi.vcall.TYPE_INT, pi.vcall.TYPE_INT, pi.vcall.TYPE_INT, pi.vcall.TYPE_INT, pi.vcall.TYPE_FLOAT, pi.vcall.TYPE_FLOAT, pi.vcall.TYPE_FLOAT, pi.vcall.TYPE_FLOAT, pi.vcall.TYPE_FLOAT, pi.vcall.TYPE_FLOAT, pi.vcall.TYPE_INT]]
		],
		objHandlesToObjs = function (scene, objHandleVector) {
			var i, num, oh, objList = [];
			num = pi.vector.getSize(objHandleVector);
			for (i = 0; i < num; i++) {
				oh = pi.vector.get(objHandleVector, i);
				objList.push(scene.getObjByHandle(oh));
			}

			return objList;
		};

	// 注册所有 vcall 函数句柄
	pi.vcall.makeVCall("s3d.dll", module, vcalls);

	/** 创建射线查询 */
	module.createRayQuery = function (scene, mask) {
		var query = {},
			objList = [],
			distances = {};

		/** 执行查询操作 */
		query.doQuery = function (start, end, forDistance) {
			var i, objList, n, f;

			pi.cbuffer.clear(distanceBuff);
			pi.vector.reset(queryList);
			pi.vector.reset(collisionList);
			vcalls.s3d_query_line(scene.handle, mask, queryList, start.x, start.y, start.z, end.x, end.y, end.z);
			vcalls.s3d_collision_rayDist(scene.handle, queryList, collisionList, distanceBuff, start.x, start.y, start.z, end.x, end.y, end.z, forDistance);
			objList = objHandlesToObjs(scene, collisionList);
			if (forDistance) {
				for (i = 0; i < objList.length; i++) {
					n = pi.cbuffer.readDouble(distanceBuff);
					f = pi.cbuffer.readDouble(distanceBuff);
					distances[objList[i].handle] = {
						near: n,
						far: f
					};
				}
			}

			return objList;
		};

		/** 获取碰撞距离 */
		query.getDist = function (obj) {
			return distances[obj.handle];
		};

		return query;
	};

	/** 创建球形查询 */
	module.createShpereQuery = function (scene, mask) {
		var query = {},
			objList = [];

		/** 执行查询操作 */
		query.doQuery = function (center, radius) {
			pi.vector.reset(queryList);
			pi.vector.reset(collisionList);
			vcalls.s3d_query_sphere(scene.handle, mask, queryList, center.x, center.y, center.z, radius);
			vcalls.s3d_collision_sphere2objs(scene.handle, queryList, collisionList, center.x, center.y, center.z, radius);
			return objHandlesToObjs(scene, collisionList);
		};

		return query;
	};

	/** 创建扇形查询 */
	module.createSectorQuery = function (scene, mask) {
		var query = {},
			objList = [];

		/** 执行查询操作 */
		query.doQuery = function (radius, radians, worldMat, splitNum) {
			splitNum = splitNum || 5;
			pi.vector.reset(queryList);
			pi.vector.reset(collisionList);
			vcalls.s3d_query_sector(scene.handle, mask, queryList, radius, radians, worldMat);
			vcalls.s3d_collision_sector2objs(scene.handle, queryList, collisionList, radius, radians, worldMat, splitNum);
			return objHandlesToObjs(scene, collisionList);
		};

		return query;
	};

	/** 创建圆锥查询 */
	module.createConeQuery = function (scene, mask) {
		var query = {},
			objList = [];

		/** 执行查询操作 */
		query.doQuery = function (radius, height, worldMat, splitNum) {
			pi.vector.reset(queryList);
			pi.vector.reset(collisionList);
			vcalls.s3d_query_cone(scene.handle, mask, queryList, radius, height, worldMat);
			vcalls.s3d_collision_cone2objs(scene.handle, queryList, collisionList, radius, height, worldMat, splitNum);
			return objHandlesToObjs(scene, collisionList);
		};
	};

	/** 创建圆柱查询 */
	module.createCylinderQuery = function (scene, mask) {
		var query = {},
			objList = [];

		/** 执行查询操作 */
		query.doQuery = function (radius, height, worldMat, splitNum) {
			pi.vector.reset(queryList);
			pi.vector.reset(collisionList);
			vcalls.s3d_query_cylinder(scene.handle, mask, queryList, radius, height, worldMat);
			vcalls.s3d_collision_cylinder2objs(scene.handle, queryList, collisionList, radius, height, worldMat, splitNum);
			return objHandlesToObjs(scene, collisionList);
		};

		return query;
	};

	/** 创建摄像机查询 */
	module.createCameraQuery = function (scene) {
		var query = {},
			objList = [];

		/** 执行查询操作 */
		query.doQuery = function (camera, mask) {
			pi.vector.reset(queryList);
			vcalls.s3d_query_frustum(scene.handle, mask, queryList, camera.getFrustumHandle());
			return objHandlesToObjs(scene, queryList);
		};

		return query;
	};

	/** 创建碰撞对查询 */
	module.createCollisionPairQuery = function (scene) {
		var query = {};

		/** 执行查询操作 */
		query.doQuery = function (mask1, mask2, solver) {
			var i, num, oh1, oh2, obj1, obj2, pairs = [], sh = scene.handle;

			pi.vector.reset(collisionList);
			num = vcalls.s3d_collide_pair(sh, mask1, mask2, collisionList);
			for (i = 0; i < num; i += 2) {
				oh1 = pi.vector.get(collisionList, i);
				oh2 = pi.vector.get(collisionList, i + 1);
				obj1 = scene.getObjByHandle(oh1);
				obj2 = scene.getObjByHandle(oh2);
				if (solver !== undefined) {
					solver(obj1, obj2);
				}
				pairs.push([obj1, obj2]);
			}

			return pairs;
		};

		return query;
	};

	return module;
});
